<?php

/**
 * 通用控制器
 * User: Administrator
 * Date: 2018/12/26
 * Time: 10:15
 */

namespace PKFrame;
defined('PATH_PK') or die();


use PKFrame\DataHandler\Arrays;
use PKFrame\DataHandler\Auth;
use PKFrame\DataHandler\Numbers;
use PKFrame\Lib\Redirect;
use PKFrame\Template\Tpl;

abstract class Controller extends Base
{
    protected static $pageIndex, $pageSize;

    abstract public function Main();

    final protected function callOfSellFunc()
    {
        $action = lcfirst(request()->action());
        if ($action != 'main' && method_exists($this, $action)) {
            $this->{$action}();
        }
    }

    /**
     * 处理请求参数中带有翻页参数
     * @param string $indexField
     * @param string $rowsField
     */
    final protected function getPages(string $indexField = 'page', string $rowsField = 'limit')
    {
        $index = request()->get($indexField);
        Numbers::Is($index) ?: $index = request()->post($indexField);
        $rows = request()->get($rowsField);
        Numbers::Is($rows) ?: $rows = request()->post($rowsField);
        self::$pageIndex = max(Numbers::Is($index), 1);
        self::$pageSize = max(Numbers::Is($rows), 10);
    }

    final protected function json($argv = [], $count = 0)
    {
        !is_string($argv) ?: $argv = language($argv);
        out()->json($argv, $count);
    }

    /**
     * 模板变量赋值
     * @access protected
     * @param $name
     *          要显示的模板变量
     * @param string $value 变量的值
     * @return $this
     */
    final protected function assign($name, $value = ''): Controller
    {
        if (is_array($name)) {
            $this->view()->SetTplParamList($name);
        } else {
            $this->view()->SetTplParam($name, $value);
        }
        return $this;
    }

    /**
     * 视图过滤 PHP
     * @access protected
     * @param string $template 模板文件名
     */
    final protected function fetchByPHP($template = '')
    {
        out()->html($this->view()->PhpDisplay($template));
    }

    /**
     * 视图过滤
     * @access protected
     * @param string $template 模板文件名
     * @param null $dir
     */
    final protected function fetch($template = '', $dir = null)
    {
        is_null($dir) ?: $this->view()->SetTplDir($dir);
        !empty($template) ?: $template = strtolower(request()->controller());
        out()->html($this->view()->Display($template));
    }

    /**
     * 处理请求参数有时间区间参数，转为 SQL 查询参数
     * @param $dbViewStartField
     * @param null $dbViewEndField
     * @param string $startTimeField
     * @param string $endTimeField
     * @return array
     */
    final protected function postByDateIntervalToSQLParam(
        $dbViewStartField,
        $dbViewEndField = null,
        $startTimeField = 'StartTime',
        $endTimeField = 'EndTime'
    ): array
    {
        $result = [];
        $startTimeFieldIsEmpty = \request()->has($startTimeField, 'post');
        $endTimeFieldIsEmpty = \request()->has($endTimeField, 'post');
        if ($startTimeFieldIsEmpty && $endTimeFieldIsEmpty) {
            $startTime = strtotime(\request()->post($startTimeField));
            $endTime = strtotime(\request()->post($endTimeField));
            $startTime < $endTime ?: $this->noticeByJson('Date_StartStop_Error');
            // 如果数据表查询的字段为相同字段可为 null
            !empty($dbViewEndField) ?: $dbViewEndField = $dbViewStartField;
            $result[] = "unix_timestamp(`{$dbViewStartField}`) >= '{$startTime}'";
            $result[] = "unix_timestamp(`{$dbViewEndField}`) <= '{$endTime}'";
        }
        return $result;
    }

    final protected function checkModel(array $list_field, array $list_from = null): array
    {
        $list_from = is_null($list_from) ? request()->post() : $list_from;
        $result = [];
        foreach ($list_field as $item) {
            !array_key_exists($item, $list_from) ?: $result[$item] = $list_from[$item];
        }
        Arrays::Is($result) ?: $this->noticeByJson('PostJSON_isEmpty');
        return $result;
    }

    final protected function checkPostFieldIsEmpty($field, $tips = null, $app = null)
    {
        $this->checkPostFieldIsExists($field, $tips);
        $data = request()->post($field);
        !is_string($data) ?: $data = trim($data);
        if (empty($data) && !is_null($tips)) {
            request()->isAjax() ? $this->noticeByJson($tips, $app) : $this->noticeByPage($tips, null, $app);
        }
        return $data;
    }

    final protected function checkPostFieldIsExists($field, $tips = null): bool
    {
        $isExists = \request()->has($field, 'post');
        if (!$isExists && !is_null($tips)) {
            request()->isAjax() ? $this->noticeByJson($tips) : $this->noticeByPage($tips);
        }
        return $isExists;
    }

    final protected function view(): Tpl
    {
        static $tpl;
        if (empty($tpl)) {
            $tpl = new Tpl();
            $path_tplParams = PATH_CACHE . 'Data' . DS . 'tpl_params.php';
            if (file_exists($path_tplParams)) {
                $res = loader($path_tplParams, true);
                $list_params = [];
                foreach ($res as $re) {
                    $list_params[$re['name']] = Auth::HtmlspecialcharsDeCode($re['value']);
                }
                $tpl->SetTplParam('params', $list_params);
            }
        }
        return $tpl;
    }

    final public static function ToMeUrl($path): string
    {
        return \request()->domain() . 'index.php/' . $path;
    }

    /**
     * URL重定向
     * @access protected
     * @param string $url 跳转的URL表达式
     * @param array $params 其它URL参数
     * @param integer $code http code
     */
    final protected function redirect(string $url, array $params = [], int $code = 302)
    {
        $response = new Redirect($url);

        if (is_integer($params)) {
            $code = $params;
            $params = [];
        }

        $response->code($code)->params($params)->send();
    }

    protected function getId(string $field, string $tips = null, string $app = null): int
    {
        $id = Numbers::To(request()->get($field));
        if (!is_null($tips)) {
            Numbers::IsId($id) ?: $this->noticeByJson($tips, $app);
        }
        return intval($id);
    }

    protected function postId(string $field, string $tips = null, string $app = null): int
    {
        $id = Numbers::To(request()->post($field));
        if (!is_null($tips)) {
            Numbers::IsId($id) ?: $this->noticeByJson($tips, $app);
        }
        return intval($id);
    }

}
